﻿using Huirui.Cavan.Domain.MainBoundedContext.SalesModule;
using Huirui.Cavan.Domain.MainBoundedContext.SearchModule;
using System;
using System.Collections;
using Huirui.Cavan.Application.MainBoundedContext.SystemModule;
using Huirui.Cavan.Domain.Seedwork;
using Spring.Context.Support;
using Huirui.Cavan.Domain.MainBoundedContext.SystemModule;
using Huirui.Cavan.Core.Extension;
using Huirui.Cavan.Domain.MainBoundedContext.StockModule;
using System.Collections.Generic;
using Huirui.Cavan.Application.MainBoundedContext.StockModule;
using System.Linq;
using Huirui.Cavan.Application.MainBoundedContext.Setting;

namespace Huirui.Cavan.Application.MainBoundedContext.SalesModule
{
	#region Sale

    public class SalesAppService : BaseAppService<Sale, string, SaleSearch, ISalesRepository>, ISalesAppService
	{
        private IStockInOutDetailAppService StockInDetailAppService { get; set; }
        private IReceivablesAppService ReceivablesAppService { get; set; }
        private IStockAppService StockAppService { get; set; }
        private IStockInOutTypeAppService StockInOutTypeAppService { get; set; }
        private IProjectAppService ProjectAppService { get; set; }
        private ICustomerAppService CustomerAppService { get; set; }
        private IWareHouseAppService WareHouseAppService { get; set; }
        private ISalesOrderAppService SalesOrderAppService { get; set; }
        private IStockInOutAppService StockInOutAppService { get; set; }

        public override BoolGenericResult<Sale> AddOrUpdate(Sale entity)
        {
            Init();
            SellProductToCustomerResult result = new SellProductToCustomerResult();
            this.StockAppService = this.SpringContext.GetObject(StockModuleConst.STOCKAPPSERVICE) as IStockAppService;
            this.StockInDetailAppService = this.SpringContext.GetObject(StockModuleConst.STOCKINOUTDETAILAPPSERVICE) as IStockInOutDetailAppService;
            this.ReceivablesAppService = this.SpringContext.GetObject(SalesModuleConst.ECEIVABLESAPPSERVICE) as IReceivablesAppService;
            this.StockInOutTypeAppService = this.SpringContext.GetObject(StockModuleConst.STOCKINOUTTYPEAPPSERVICE) as IStockInOutTypeAppService;
            this.ProjectAppService = this.SpringContext.GetObject(SystemModuleConst.PROJECTAPPSERVICE) as IProjectAppService;
            this.CustomerAppService = this.SpringContext.GetObject(SystemModuleConst.CUSTOMERAPPSERVICE) as ICustomerAppService;
            this.WareHouseAppService = this.SpringContext.GetObject(StockModuleConst.WAREHOUSEAPPSERVICE) as IWareHouseAppService;
            this.SalesOrderAppService = this.SpringContext.GetObject(SalesModuleConst.SALESORDERAPPSERVICE) as ISalesOrderAppService;
            this.StockInOutAppService = this.SpringContext.GetObject(StockModuleConst.STOCKINOUTAPPSERVICE) as IStockInOutAppService;

            Employee employee = this.EmployeeAppService.GetSingleBySearch(SearchFactory.CreateEmployeeSearch(SecurityAppService.UserAccount.Id));
            Seller seller = new Seller(employee);

            Sale oldSale = null;
            Receivables oldReceivables = null;
            if (entity.Id.IsNotEmpty())
            {
                oldSale = this.Repository.Get(entity.Id);
            }

            if (entity.SalesOrder.IsNotNull() && entity.SalesOrder.Id.IsNotEmpty())
            {
                entity.SalesOrder = this.SalesOrderAppService.GetById(entity.SalesOrder.Id);
            }
            if (entity.Project.IsNotNull() && entity.Project.Id.IsNotEmpty())
            {
                entity.Project = this.ProjectAppService.GetById(entity.Project.Id);
            }
            if (entity.Customer.IsNotNull() && entity.Customer.Id.IsNotEmpty())
            {
                entity.Customer = this.CustomerAppService.GetById(entity.Customer.Id);
            }
            if (entity.SaleEmployee.IsNotNull() && entity.SaleEmployee.Id.IsNotEmpty())
            {
                entity.SaleEmployee = this.EmployeeAppService.GetById(entity.SaleEmployee.Id);
            }
            if (entity.WareHouse.IsNotNull() && entity.WareHouse.Id.IsNotEmpty())
            {
                entity.WareHouse = this.WareHouseAppService.GetById(entity.WareHouse.Id);
            }

            StockInOutType stockInOutType = this.StockInOutTypeAppService.GetById(4);

            List<StockInOutDetail> stockInDetails = new List<StockInOutDetail>();
            foreach (StockInOutDetail siod in entity.StockInOut.StockInOutDetails)
            {
                IList<StockInOutDetail> tempStockInDetails = this.StockInDetailAppService.GetBySearch(SearchFactory.CreateStockInDetailSearch(siod.Stock.Id, true)).ToList();
                if (tempStockInDetails.IsNotNull())
                {
                    stockInDetails.AddRange(tempStockInDetails);
                }
                siod.WareHouse = entity.WareHouse;
                siod.Stock = this.StockAppService.GetById(siod.Stock.Id);
                siod.Stock.StockByWareHouseReports = this.StockAppService.GetStocksByWareHouseReport(entity.WareHouse.Id, siod.Stock.Id);
            }

            if (oldSale.IsNull())
            {
                IIDGenerateAppService idGenerateAppService = this.SpringContext.GetObject(SystemModuleConst.IDGENERATEAPPSERVICE, new object[] { employee.Corporation }) as IIDGenerateAppService;
                entity.Id = idGenerateAppService.GenerateID(SystemIdentifier.ReceiptCodeRuleType.Sale);

                if (entity.SalesOrder.IsNotNull())
                {
                    if (HuiruiProject.UserSettings.SalesOrderShouldBeChecked && entity.SalesOrder.CheckedStatus != SystemIdentifier.CheckedStatus.Pass)
                    {
                        result.IsSuccess = false;
                        result.Messages.Add("销售订单需先审核");
                        return result;
                    }
                }

                result = seller.SellProductToCustomer(entity.Id, entity.SalesDate, entity.DeliveryCode, entity.DeliveryAddress, entity.CustomerOrderCode,
                    entity.CheckCode, entity.CheckType, entity.Remark, entity.DiscountRate, entity.ReceiptType, entity.ReceiptCondition, 0,
                    entity.PayDay, entity.DeadDate, entity.Currency, entity.CurrencyRate, entity.TaxRate,
                    entity.Customer, entity.SaleEmployee, entity.Project, entity.WareHouse, entity.SalesOrder, entity.ReceiptAccount, entity.ReceiptEmployee, entity.StockInOut, stockInDetails, stockInOutType);
                if (result.IsSuccess)
                {
                    result.Object.StockInOut.Id = idGenerateAppService.GenerateID(SystemIdentifier.ReceiptCodeRuleType.StockOut);
                    base.Add(result.Object);
                    this.ReceivablesAppService.Add(result.OtherReceivables);
                    this.SalesOrderAppService.Update(entity.SalesOrder);
                    foreach (StockInOutDetail sid in stockInDetails)
                    {
                        this.StockInDetailAppService.Update(sid);
                    }
                    foreach (StockInOutDetail siod in entity.StockInOut.StockInOutDetails)
                    {
                        this.StockAppService.Update(siod.Stock);
                    }
                }
            }
            else
            {
                oldReceivables = this.ReceivablesAppService.GetSingleBySearch(SearchFactory.CreateReceivablesSearch(SalesIdentifier.ReceivablesType.Sales.GetHashCode(), oldSale.Id));
                result = seller.UpdateProductToCustomer(oldSale, oldReceivables, entity.SalesDate, entity.DeliveryCode, entity.DeliveryAddress, entity.CustomerOrderCode,
                    entity.CheckCode, entity.CheckType, entity.Remark, entity.DiscountRate , entity.ReceiptType, entity.ReceiptCondition, 0,
                    entity.PayDay, entity.DeadDate, entity.Currency, entity.CurrencyRate, entity.TaxRate,
                    entity.Customer, entity.SaleEmployee, entity.Project, entity.WareHouse, entity.SalesOrder, entity.ReceiptAccount, entity.ReceiptEmployee, entity.StockInOut);
                if (result.IsSuccess)
                    return base.Update(result.Object);
            }
            result.Messages.Add("保存成功");

            return result;
        }
	}
	#endregion
}